package state;

import state.bean.GamePoint;
import state.util.GameColor;
import state.util.Hashtable;

/**
 * Class thực hiện hiệu ứng chuyển màn hình
 * 
 * @author ptran2
 * @version 0.2
 */
public class Transformer extends GameForm {

  /** Form hiện tại dịch sang trái, form tiếp theo từ bên phải màn hình dịch vào */
  public static final int TRANSFORM_MOVE_LEFT = 0;

  /** Form hiện tại dịch sang phải, form tiếp theo từ bên trái màn hình dịch vào */
  public static final int TRANSFORM_MOVE_RIGHT = 1;

  /** Kiểu cửa sổ mở ra từ giữa, mà hình mới sẽ xuất hiện ở giữa màn hình cũ */
  public static final int TRANSFORM_CLIP_WIDE_OPEN_FROM_CENTER = 2;

  /** Cửa sổ mới sẽ xuất hiện dưới dạng khung hình chữ thập ở giữa cửa sổ cũ rồi mở to dần đến khi chiếm hết màn hình */
  public static final int TRANSFORM_CLIP_BREAK_OLD_FORM = 3;

  /** Kiểu cửa sổ đóng từ hai bên khéo vào giữa cửa sổ cũ sẽ bị hẹp dần cho đến khi biến mất hẳn */
  public static final int TRANSFORM_CLIP_CLOSE_TO_CENTER = 4;

  /** Kiểu hình chữ thập khép dần từ ngoài vào giữa, cửa sổ cũ sẽ bị thu hẹp dần cho đến khi mất hẳn */
  public static final int TRANSFORM_CLIP_JOIN_NEW_FORM = 5;

  /** Kiểu chuyển sang form loading trước rồi mới chuyển sang form mới sau, dùng trong việc tiết kiệm bộ nhớ */
  public static final int TRANSFORM_WITH_LOADING_FORM = 6;

  private final int MOVE_STEP = 40;

  private int transformType = 0;
  private GameForm currentState = null;
  private GameForm nextState = null;

  private GameImage nextStateImage = null;
  private GameImage currentStateImage = null;
  private GamePoint currentStateLocation = null;
  private GamePoint nextStateLocation = null;
  private GamePoint clipLocation = null;
  private GamePoint clipSize = null;
  private int centerAreaSize = 0;

  public void transform(GameForm currentState1, GameForm nextState1, final Hashtable params1, int transformType1) {
    this.currentState = currentState1;
    this.nextState = nextState1;
    this.transformType = transformType1;

    if (transformType1 != TRANSFORM_WITH_LOADING_FORM) {
      nextStateImage = GameImage.createImage2(GameConstants.SCREEN_WIDTH, GameConstants.SCREEN_HEIGHT);
      currentStateImage = GameImage.createImage2(GameConstants.SCREEN_WIDTH, GameConstants.SCREEN_HEIGHT);
      currentState1.setScreen(currentStateImage);
      nextState1.setScreen(nextStateImage);
    }

    switch (transformType1) {
    case TRANSFORM_MOVE_LEFT:
      currentStateLocation = GamePoint.createNewOrSetValue(currentStateLocation, 0, 0);
      nextStateLocation = GamePoint.createNewOrSetValue(nextStateLocation, GameConstants.SCREEN_WIDTH, 0);
      break;
    case TRANSFORM_MOVE_RIGHT:
      currentStateLocation = GamePoint.createNewOrSetValue(currentStateLocation, 0, 0);
      nextStateLocation = GamePoint.createNewOrSetValue(nextStateLocation, -GameConstants.SCREEN_WIDTH, 0);
      break;
    case TRANSFORM_CLIP_WIDE_OPEN_FROM_CENTER:
      clipSize = GamePoint.createNewOrSetValue(clipSize, 0, GameConstants.SCREEN_HEIGHT);
      clipLocation = GamePoint.createNewOrSetValue(clipLocation, GameConstants.SCREEN_WIDTH / 2, 0);
      break;
    case TRANSFORM_CLIP_CLOSE_TO_CENTER:
      clipSize = GamePoint.createNewOrSetValue(clipSize, GameConstants.SCREEN_WIDTH, GameConstants.SCREEN_HEIGHT);
      clipLocation = GamePoint.createNewOrSetValue(clipLocation, 0, 0);
      break;
    case TRANSFORM_CLIP_BREAK_OLD_FORM:
      centerAreaSize = MOVE_STEP;
      break;
    case TRANSFORM_CLIP_JOIN_NEW_FORM:
      centerAreaSize = GameConstants.SCREEN_HEIGHT;
      break;
    }

    if (!this.nextState.isRunning && (transformType1 != TRANSFORM_WITH_LOADING_FORM)) {
      this.nextState.isRunning = true;
      this.nextState.init(params1);
    }

    isRunning = true;
    GameGlobal.systemCanvas.beginTransform();

    if (transformType1 == TRANSFORM_WITH_LOADING_FORM) {
      GameGlobal.alert.showAlert2(this, GameAlert.LOADING_FORM, "", 0);
      new GameControl() {
        public void perform() {
          GameGlobal.alert.setLoadingPercent((byte) 20);
          ResourceManager.clearIDLEResource();
          if (Transformer.this.currentState != null) {
            Transformer.this.currentState.detroyAll();
            Transformer.this.currentState = null;
          }
          GameGlobal.alert.setLoadingPercent((byte) 40);
          Transformer.this.nextState.isRunning = true;
          Transformer.this.nextState.init(params1);
          GameGlobal.alert.setLoadingPercent((byte) 70);
          GameGlobal.alert.setLoadingPercent((byte) 80);
          GameGlobal.systemCanvas.hideAlert();
          GameGlobal.systemCanvas.endTransform(Transformer.this.nextState, false);
        }
      }.start();
    }
  }

  public GameForm getOldState() {
    return currentState;
  }

  public void draw(Graphics g) {
    if (transformType == TRANSFORM_WITH_LOADING_FORM) {
      g.setColor(GameColor.BLACK_CODE);
      g.fillRect(0, 0, GameConstants.SCREEN_WIDTH, GameConstants.SCREEN_HEIGHT);
      return;
    }

    currentState.updateFullScreen();
    nextState.updateFullScreen();
    g.setColor(GameColor.WHITE_CODE);
    g.fillRect(0, 0, GameConstants.SCREEN_WIDTH, GameConstants.SCREEN_HEIGHT);

    switch (transformType) {
    case TRANSFORM_MOVE_LEFT:
      if (nextStateLocation._x > 0) {
        currentStateLocation._x -= MOVE_STEP;
        nextStateLocation._x -= MOVE_STEP;
        g.drawImage(currentStateImage, currentStateLocation._x, currentStateLocation._y, GameConstants.TOP_LEFT_ANCHOR);
        g.drawImage(nextStateImage, nextStateLocation._x, nextStateLocation._y, GameConstants.TOP_LEFT_ANCHOR);
      } else {
        g.drawImage(nextStateImage, 0, 0, GameConstants.TOP_LEFT_ANCHOR);
        GameGlobal.systemCanvas.endTransform(nextState, true);
      }
      break;
    case TRANSFORM_MOVE_RIGHT:
      if (nextStateLocation._x < 0) {
        currentStateLocation._x += MOVE_STEP;
        nextStateLocation._x += MOVE_STEP;
        g.drawImage(currentStateImage, currentStateLocation._x, currentStateLocation._y, GameConstants.TOP_LEFT_ANCHOR);
        g.drawImage(nextStateImage, nextStateLocation._x, nextStateLocation._y, GameConstants.TOP_LEFT_ANCHOR);
      } else {
        g.drawImage(nextStateImage, 0, 0, GameConstants.TOP_LEFT_ANCHOR);
        GameGlobal.systemCanvas.endTransform(nextState, true);
      }
      break;
    case TRANSFORM_CLIP_WIDE_OPEN_FROM_CENTER:
      if (clipSize._x < GameConstants.SCREEN_WIDTH) {
        clipSize._x += MOVE_STEP;
        clipLocation._x -= (MOVE_STEP / 2);

        g.setClip(0, 0, GameConstants.SCREEN_WIDTH, GameConstants.SCREEN_HEIGHT);
        g.drawImage(currentStateImage, 0, 0, GameConstants.TOP_LEFT_ANCHOR);
        g.setClip(clipLocation._x, clipLocation._y, clipSize._x, clipSize._y);
        g.drawImage(nextStateImage, 0, 0, GameConstants.TOP_LEFT_ANCHOR);
      } else {
        g.setClip(0, 0, GameConstants.SCREEN_WIDTH, GameConstants.SCREEN_HEIGHT);
        g.drawImage(nextStateImage, 0, 0, GameConstants.TOP_LEFT_ANCHOR);
        GameGlobal.systemCanvas.endTransform(nextState, true);
      }
      break;
    case TRANSFORM_CLIP_CLOSE_TO_CENTER:
      if (clipSize._x > 0) {
        clipSize._x -= MOVE_STEP;
        clipLocation._x += (MOVE_STEP / 2);

        g.setClip(0, 0, GameConstants.SCREEN_WIDTH, GameConstants.SCREEN_HEIGHT);
        g.drawImage(nextStateImage, 0, 0, GameConstants.TOP_LEFT_ANCHOR);
        g.setClip(clipLocation._x, clipLocation._y, clipSize._x, clipSize._y);
        g.drawImage(currentStateImage, 0, 0, GameConstants.TOP_LEFT_ANCHOR);
      } else {
        g.setClip(0, 0, GameConstants.SCREEN_WIDTH, GameConstants.SCREEN_HEIGHT);
        g.drawImage(nextStateImage, 0, 0, GameConstants.TOP_LEFT_ANCHOR);
        GameGlobal.systemCanvas.endTransform(nextState, true);
      }
      break;
    case TRANSFORM_CLIP_BREAK_OLD_FORM:
      if (centerAreaSize < GameConstants.SCREEN_HEIGHT) {
        g.setClip(0, 0, GameConstants.SCREEN_WIDTH, GameConstants.SCREEN_HEIGHT);
        g.drawImage(nextStateImage, 0, 0, GameConstants.TOP_LEFT_ANCHOR);

        int width1 = (GameConstants.SCREEN_WIDTH - centerAreaSize) / 2;
        int height1 = (GameConstants.SCREEN_HEIGHT - centerAreaSize) / 2;
        g.setClip(0, 0, width1, height1);
        g.drawImage(currentStateImage, 0, 0, GameConstants.TOP_LEFT_ANCHOR);
        g.setClip((GameConstants.SCREEN_WIDTH + centerAreaSize) / 2, 0, width1, height1);
        g.drawImage(currentStateImage, 0, 0, GameConstants.TOP_LEFT_ANCHOR);
        g.setClip(0, (GameConstants.SCREEN_HEIGHT + centerAreaSize) / 2, width1, height1);
        g.drawImage(currentStateImage, 0, 0, GameConstants.TOP_LEFT_ANCHOR);
        g.setClip((GameConstants.SCREEN_WIDTH + centerAreaSize) / 2, (GameConstants.SCREEN_HEIGHT + centerAreaSize) / 2, width1, height1);
        g.drawImage(currentStateImage, 0, 0, GameConstants.TOP_LEFT_ANCHOR);
        centerAreaSize += MOVE_STEP;
      } else {
        g.setClip(0, 0, GameConstants.SCREEN_WIDTH, GameConstants.SCREEN_HEIGHT);
        g.drawImage(nextStateImage, 0, 0, GameConstants.TOP_LEFT_ANCHOR);
        GameGlobal.systemCanvas.endTransform(nextState, true);
      }
      break;
    case TRANSFORM_CLIP_JOIN_NEW_FORM:
      if (centerAreaSize > -MOVE_STEP) {
        if (centerAreaSize < 0) {
          centerAreaSize = 0;
        }
        g.setClip(0, 0, GameConstants.SCREEN_WIDTH, GameConstants.SCREEN_HEIGHT);
        g.drawImage(currentStateImage, 0, 0, GameConstants.TOP_LEFT_ANCHOR);

        int width1 = (GameConstants.SCREEN_WIDTH - centerAreaSize) / 2;
        int height1 = (GameConstants.SCREEN_HEIGHT - centerAreaSize) / 2;
        g.setClip(0, 0, width1, height1);
        g.drawImage(nextStateImage, 0, 0, GameConstants.TOP_LEFT_ANCHOR);
        g.setClip((GameConstants.SCREEN_WIDTH + centerAreaSize) / 2, 0, width1, height1);
        g.drawImage(nextStateImage, 0, 0, GameConstants.TOP_LEFT_ANCHOR);
        g.setClip(0, (GameConstants.SCREEN_HEIGHT + centerAreaSize) / 2, width1, height1);
        g.drawImage(nextStateImage, 0, 0, GameConstants.TOP_LEFT_ANCHOR);
        g.setClip((GameConstants.SCREEN_WIDTH + centerAreaSize) / 2, (GameConstants.SCREEN_HEIGHT + centerAreaSize) / 2, width1, height1);
        g.drawImage(nextStateImage, 0, 0, GameConstants.TOP_LEFT_ANCHOR);
        centerAreaSize -= MOVE_STEP;
      } else {
        g.setClip(0, 0, GameConstants.SCREEN_WIDTH, GameConstants.SCREEN_HEIGHT);
        g.drawImage(nextStateImage, 0, 0, GameConstants.TOP_LEFT_ANCHOR);
        GameGlobal.systemCanvas.endTransform(nextState, true);
      }
      break;
    }
  }

  public void destroy() {
    if (currentState != null) {
      currentState.isRunning = false;
      currentState = null;
    }
    nextState = null;
    nextStateImage = null;
    currentStateImage = null;
    currentStateLocation = null;
    nextStateLocation = null;
    clipLocation = null;
    clipSize = null;
  }
}
